<template>
  <div class="starry-sky">
    <canvas ref="canvas" id="canvas"></canvas>
  </div>
</template>

<script>
export default {
  name: "Star",
  mounted() {
    document.title = "星空";
    function Star(id, x, y) {
      this.id = id;
      this.x = x;
      this.y = y;
      this.r = Math.floor(Math.random() * 2) + 1;
      var alpha = (Math.floor(Math.random() * 10) + 1) / 10 / 2;
      this.color = "rgba(255,255,255," + alpha + ")";
    }

    Star.prototype.draw = function () {
      ctx.fillStyle = this.color;
      ctx.shadowBlur = this.r * 2;
      ctx.beginPath();
      ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);
      ctx.closePath();
      ctx.fill();
    };

    Star.prototype.move = function () {
      this.y -= 0.15;
      if (this.y <= -10) this.y = HEIGHT + 10;
      this.draw();
    };

    Star.prototype.die = function () {
      stars[this.id] = null;
      delete stars[this.id];
    };

    function Dot(id, x, y, r) {
      this.id = id;
      this.x = x;
      this.y = y;
      this.r = Math.floor(Math.random() * 5) + 1;
      this.maxLinks = 2;
      this.speed = 0.5;
      this.a = 0.5;
      this.aReduction = 0.005;
      this.color = "rgba(255,255,255," + this.a + ")";
      this.linkColor = "rgba(255,255,255," + this.a / 4 + ")";

      this.dir = Math.floor(Math.random() * 140) + 200;
    }

    Dot.prototype.draw = function () {
      ctx.fillStyle = this.color;
      ctx.shadowBlur = this.r * 2;
      ctx.beginPath();
      ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);
      ctx.closePath();
      ctx.fill();
    };

    Dot.prototype.link = function () {
      if (this.id == 0) return;
      var previousDot1 = getPreviousDot(this.id, 1);
      var previousDot2 = getPreviousDot(this.id, 2);
      var previousDot3 = getPreviousDot(this.id, 3);
      if (!previousDot1) return;
      ctx.strokeStyle = this.linkColor;
      ctx.moveTo(previousDot1.x, previousDot1.y);
      ctx.beginPath();
      ctx.lineTo(this.x, this.y);
      if (previousDot2 != false) ctx.lineTo(previousDot2.x, previousDot2.y);
      if (previousDot3 != false) ctx.lineTo(previousDot3.x, previousDot3.y);
      ctx.stroke();
      ctx.closePath();
    };

    function getPreviousDot(id, stepback) {
      if (id == 0 || id - stepback < 0) return false;
      if (typeof dots[id - stepback] != "undefined") return dots[id - stepback];
      else return false; //getPreviousDot(id - stepback);
    }

    Dot.prototype.move = function () {
      this.a -= this.aReduction;
      if (this.a <= 0) {
        this.die();
        return;
      }
      this.color = "rgba(255,255,255," + this.a + ")";
      this.linkColor = "rgba(255,255,255," + this.a / 4 + ")";
      (this.x = this.x + Math.cos(degToRad(this.dir)) * this.speed),
        (this.y = this.y + Math.sin(degToRad(this.dir)) * this.speed);

      this.draw();
      this.link();
    };

    Dot.prototype.die = function () {
      dots[this.id] = null;
      delete dots[this.id];
    };

    var canvas = document.getElementById("canvas"),
      ctx = canvas.getContext("2d"),
      WIDTH,
      HEIGHT,
      mouseMoving = false,
      mouseMoveChecker,
      mouseX,
      mouseY,
      stars = [],
      initStarsPopulation = 80,
      dots = [],
      dotsMinDist = 2,
      maxDistFromCursor = 50;

    setCanvasSize();
    init();

    function setCanvasSize() {
      (WIDTH = document.documentElement.clientWidth),
        (HEIGHT = document.documentElement.clientHeight);

      canvas.setAttribute("width", WIDTH);
      canvas.setAttribute("height", HEIGHT);
    }

    function init() {
      ctx.strokeStyle = "white";
      ctx.shadowColor = "white";
      for (var i = 0; i < initStarsPopulation; i++) {
        stars[i] = new Star(
          i,
          Math.floor(Math.random() * WIDTH),
          Math.floor(Math.random() * HEIGHT)
        );
        //stars[i].draw();
      }
      ctx.shadowBlur = 0;
      animate();
    }

    function animate() {
      ctx.clearRect(0, 0, WIDTH, HEIGHT);

      for (var i in stars) {
        stars[i].move();
      }
      for (var i in dots) {
        dots[i].move();
      }
      drawIfMouseMoving();
      requestAnimationFrame(animate);
    }

    window.onmousemove = function (e) {
      mouseMoving = true;
      mouseX = e.clientX;
      mouseY = e.clientY;
      clearInterval(mouseMoveChecker);
      mouseMoveChecker = setTimeout(function () {
        mouseMoving = false;
      }, 100);
    };

    function drawIfMouseMoving() {
      if (!mouseMoving) return;

      if (dots.length == 0) {
        dots[0] = new Dot(0, mouseX, mouseY);
        dots[0].draw();
        return;
      }

      var previousDot = getPreviousDot(dots.length, 1);
      var prevX = previousDot.x;
      var prevY = previousDot.y;

      var diffX = Math.abs(prevX - mouseX);
      var diffY = Math.abs(prevY - mouseY);

      if (diffX < dotsMinDist || diffY < dotsMinDist) return;

      var xVariation = Math.random() > 0.5 ? -1 : 1;
      xVariation = xVariation * Math.floor(Math.random() * maxDistFromCursor) + 1;
      var yVariation = Math.random() > 0.5 ? -1 : 1;
      yVariation = yVariation * Math.floor(Math.random() * maxDistFromCursor) + 1;
      dots[dots.length] = new Dot(dots.length, mouseX + xVariation, mouseY + yVariation);
      dots[dots.length - 1].draw();
      dots[dots.length - 1].link();
    }
    //setInterval(drawIfMouseMoving, 17);

    function degToRad(deg) {
      return deg * (Math.PI / 180);
    }
  },
};
// export default {
//   name: "Star",
//   props: {
//     point: {
//       type: Number,
//       default: 25, // 生成的星星（点）的个数, 默认25个
//     },
//     lineColor: {
//       type: String,
//       default: "rgba(45,140,210,0.2)", // 线的颜色
//     },
//     roundColor: {
//       type: String,
//       default: "rgba(45,140,210,0.1)", // 星星的颜色
//     },
//   },
//   data() {
//     return {
//       docWidth: 0, // 画布宽
//       docHeight: 0, // 画布高
//       context: null, // canvasDom的执行上下文
//       circleArr: [], // 圆点数组
//       timer: null, // 定时器对象
//     };
//   },
//   mounted() {
//     const canvasDom = this.$refs.canvas;

//     // 取画布的高宽来设置显示分辨率
//     this.docWidth = canvasDom.offsetWidth;
//     this.docHeight = canvasDom.offsetHeight;

//     // 设置画布分辨率
//     canvasDom.width = canvasDom.offsetWidth;
//     canvasDom.height = canvasDom.offsetHeight;

//     // 初始化canvas上下文
//     this.context = canvasDom.getContext("2d");

//     // 设置线条和星星颜色
//     this.context.strokeStyle = this.lineColor;
//     this.context.lineWidth = 1;
//     this.context.fillStyle = this.roundColor;

//     // 初始化
//     this.createCircleArr(); // 设置星星数组
//     this.draw(); // 首屏绘制
//     this.cycleDraw(); // 循环绘制
//   },
//   methods: {
//     /**
//      * 生成min和max之间随机数
//      */
//     rangeRadom(max, min) {
//       return Math.floor(Math.random() * (max - min + 1) + min);
//     },
//     /**
//      * 绘制原点
//      */
//     drawCircle(context, x, y, r, moveX, moveY) {
//       let circle = {
//         x,
//         y,
//         r,
//         moveX,
//         moveY,
//       };
//       context.beginPath();
//       context.arc(circle.x, circle.y, circle.r, 0, 2 * Math.PI);
//       context.closePath();
//       context.fill();
//       return circle;
//     },
//     /**
//      * 绘制线条
//      */
//     drawLine(context, beginX, beginY, closeX, closeY, opacity) {
//       context.beginPath();
//       context.strokeStyle = `rgba(0, 0, 0, ${opacity})`;
//       context.moveTo(beginX, beginY);
//       context.lineTo(closeX, closeY);
//       context.closePath();
//       context.stroke();
//     },
//     /**
//      * 生成圆点数组
//      */
//     createCircleArr() {
//       for (let i = 0; i < this.point; i++) {
//         this.circleArr.push(
//           this.drawCircle(
//             this.context,
//             this.rangeRadom(this.docWidth, 0),
//             this.rangeRadom(this.docHeight, 0),
//             this.rangeRadom(15, 2),
//             this.rangeRadom(10, -10) / 40,
//             this.rangeRadom(10, -10) / 40
//           )
//         );
//       }
//     },
//     /**
//      * 每一帧绘制
//      */
//     draw() {
//       const circleArr = this.circleArr;
//       this.context.clearRect(0, 0, this.docWidth, this.docHeight);
//       // 循环绘制点
//       for (let i = 0; i < this.point; i++) {
//         this.drawCircle(this.context, circleArr[i].x, circleArr[i].y, circleArr[i].r);
//       }
//       // 循环绘制线
//       for (let i = 0; i < this.point; i++) {
//         for (let j = 0; j < this.point; j++) {
//           if (i + j < this.point) {
//             let A = Math.abs(circleArr[i + j].x - circleArr[i].x);
//             let B = Math.abs(circleArr[i + j].y - circleArr[i].y);
//             let lineLength = Math.sqrt(A * A + B * B);
//             let C = (1 / lineLength) * 7 - 0.009;
//             let lineOpacity = C > 0.03 ? 0.03 : C;
//             if (lineOpacity > 0) {
//               this.drawLine(
//                 this.context,
//                 circleArr[i].x,
//                 circleArr[i].y,
//                 circleArr[i + j].x,
//                 circleArr[i + j].y,
//                 lineOpacity
//               );
//             }
//           }
//         }
//       }
//     },
//     /**
//      * 循环绘制
//      */
//     cycleDraw() {
//       this.timer = setInterval(() => {
//         for (let i = 0; i < this.point; i++) {
//           let cir = this.circleArr[i];
//           cir.x += cir.moveX;
//           cir.y += cir.moveY;
//           if (cir.x > this.docWidth) {
//             cir.x = 0;
//           } else if (cir.x < 0) {
//             cir.x = this.docWidth;
//           }
//           if (cir.y > this.docHeight) {
//             cir.y = 0;
//           } else if (cir.y < 0) {
//             cir.y = this.docHeight;
//           }
//         }
//         this.draw();
//       }, 10);
//     },
//   },
//   beforeDestory() {
//     // 记得摧毁定时器
//     clearInterval(this.timer);
//   },
// };
</script>

<style lang="less" scoped>
.starry-sky {
  width: 100%;
  height: 100%;
  & canvas {
    width: 100%;
    height: 100%;
  }
}
</style>
